package edu.ccut.saturn.component.impl.node;

import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.dom4j.Document;
import org.dom4j.Element;
import org.json.JSONException;
import org.json.JSONObject;

import edu.ccut.saturn.component.ComponentManager;
import edu.ccut.saturn.component.IActionContext;
import edu.ccut.saturn.component.IDataInfo;
import edu.ccut.saturn.component.IDataItem;
import edu.ccut.saturn.component.ILogicContext;
import edu.ccut.saturn.component.IParameterContext;
import edu.ccut.saturn.component.IParameterInfo;
import edu.ccut.saturn.component.SaturnData;
import edu.ccut.saturn.component.SaturnDataManager;
import edu.ccut.saturn.component.SaturnDebugThreadsManager;
import edu.ccut.saturn.component.impl.SaturnParameterInfo;
import edu.ccut.saturn.component.loader.node.DataNodeInfoLoader;
import edu.ccut.saturn.component.loader.node.NodeInfoLoader;
import edu.ccut.saturn.component.utils.ExceptionUtils;
import edu.ccut.saturn.component.xml.Dom4jUtils;
import edu.ccut.saturn.component.xml.ISaturnElement;
import edu.ccut.saturn.component.xml.SaturnElement;

/**
 * 数据结点的实现类。在action组件、logic组件中调用数据结点，数据结点负责把用户从页面
 * 输入的信息组装成数据项，具体转换的类型有SaturnData, list或map类型，其中数据项的定义由数据组件来描述;
 * <p>
 * 接收待转换数据的方式有两种，xml和request。xml指从request域接收一个xml格式数据描述的字符串，描述了待组装的信息，
 * 数据结点每次只组装一个结点的信息；request指直接从request域中匹配变量并组装陈数据项。
 * 组装的过程是按照数据项的字段名匹配输入的变量名或带有指定前缀的变量名，然后把符合条件的变量组装成数据项。
 * list类型中的元素必须是SaturnData类型的数据。
 * <p>
 * 类<code>SaturnDataNodeInfo</code>扩展了<code>AbstractNodeInfo</code>：
 * <li>字段<code>prefix</code>：描述接收的变量名称的前缀信息，如果不为空则只接收以字段值为前缀的变量名称；
 * <li>字段<code>scope</code>：记录了接收数据的方式；目前支持xml和request域两种方式；
 * <li>字段<code>dataKey</code>：记录了组装好的数据在logic或action上下文中的键值；
 * <li>字段<code>classType</code>：记录了要组装的数据的类型，支持三种数据类型：list、map、saturnData；
 * <li>字段<code>saturnDataNamespace</code>：记录了数据组件的命名空间的值；
 * <li>字段<code>saturnDataType</code>：记录了数据组件的名称；
 * <li>字段<code>xmlKey</code>：记录了接收xml数据组装数据项时，在request域中获得xml数据的变量名称；
 * <li>字段<code>elementKey</code>：记录了标识要解析的xml数据中的结点的属性值。
 * TODO：插件界面上给出的接收方式过多
 * 
 * @author 谷钰
 * @author 温建
 * 
 * @version 1.0 2008.8.22
 * 
 * @see AbstractNodeInfo
 * @see ILogicContext
 * @see IParameterContext
 * 
 */
public class SaturnDataNodeInfo extends AbstractNodeInfo {

	private String prefix = null;

	private String scope = "1";

	private String dataKey = null;

	private String classType = null;

	private String saturnDataNamespace = null;

	private String saturnDataType = null;

	private String xmlKey = null;

	private String elementKey = null;

	private static final String DATA_KEY_SEPARATOR = "_";

	private static final String SCOPE_XML = "xml";

	// emily
	private static final String SCOPE_JSON = "json";

	private static final String DATA_KEY_LIST = "list";

	private static final String DATA_DATAS_VALUE = "value";

	private static final String DATA_DATAS_KEY = "key";

	private static final String DATA_DATAS_MAP = "map";

	private static final String DATA_DATAS_LIST = "list";

	private boolean hasPrefix = false;

	public SaturnDataNodeInfo(String id, String name, String description,
			String nextId, String scope, String prefix, String dataKey,
			String classType, String namespace, String saturnDataType,
			String xmlKey, String elementKey, String x, String y) {

		super(id, name, description, nextId, null, x, y, "saturn-data");

		this.prefix = prefix;
		this.scope = scope;
		this.dataKey = dataKey;
		this.classType = classType;
		this.saturnDataNamespace = namespace;
		this.saturnDataType = saturnDataType;
		this.xmlKey = xmlKey;
		this.elementKey = elementKey;
		if (prefix != null && !"".equals(prefix)) {
			hasPrefix = true;
		}
	}

	/**
	 * 获得接收数据的前缀
	 * 
	 * @return
	 */
	public String getPrefix() {
		return prefix;
	}

	/**
	 * 获得接收xml数据的变量名称
	 * 
	 * @return
	 */
	public String getXmlKey() {
		return xmlKey;
	}

	/**
	 * 设置接收xml数据的变量名称
	 * 
	 * @param xmlKey
	 */
	public void setXmlKey(String xmlKey) {
		this.xmlKey = xmlKey;
	}

	/**
	 * 获得标识要解析的xml数据中的结点的属性值
	 * 
	 * @return
	 */
	public String getElementKey() {
		return elementKey;
	}

	/**
	 * 设置标识要解析的xml数据中的结点的属性值
	 * 
	 * @param elementKey
	 */
	public void setElementKey(String elementKey) {
		this.elementKey = elementKey;
	}

	/**
	 * 设置接收数据的前缀
	 * 
	 * @param prefix
	 */
	public void setPrefix(String prefix) {
		this.prefix = prefix;
	}

	/**
	 * 获得接收数据的方式
	 * 
	 * @return
	 */
	public String getScope() {
		return scope;
	}

	/**
	 * 设置接收数据的方式
	 * 
	 * @param scope
	 */
	public void setScope(String scope) {
		this.scope = scope;
	}

	/**
	 * 获得生成数据在上下文中的存放位置
	 * 
	 * @return
	 */
	public String getDataKey() {
		return dataKey;
	}

	/**
	 * 设置生成数据在上下文中的存放位置
	 * 
	 * @param dataKey
	 */
	public void setDataKey(String dataKey) {
		this.dataKey = dataKey;
	}

	/**
	 * 获得待生成的数据的类型
	 * 
	 * @return
	 */
	public String getDataType() {
		return classType;
	}

	/**
	 * 设置待生成的数据的类型
	 * 
	 * @param dataType
	 */
	public void setDataType(String dataType) {
		this.classType = dataType;
	}

	/**
	 * 获得待生成的SaturnData数据项的命名空间
	 * 
	 * @return
	 */
	public String getSaturnDataNamespace() {
		return saturnDataNamespace;
	}

	/**
	 * 设置待生成的SaturnData数据项的命名空间
	 * 
	 * @param saturnDataNamespace
	 */
	public void setSaturnDataNamespace(String saturnDataNamespace) {
		this.saturnDataNamespace = saturnDataNamespace;
	}

	/**
	 * 获得待生成的SaturnData数据项的名称
	 * 
	 * @return
	 */
	public String getSaturnDataType() {
		return saturnDataType;
	}

	/**
	 * 设置待生成的SaturnData的数据项的名称
	 * 
	 * @param saturnDataType
	 */
	public void setSaturnDataType(String saturnDataType) {
		this.saturnDataType = saturnDataType;
	}

	/**
	 * 数据结点的执行逻辑。
	 * 如果以xml方式接收数据，首先从request域获得xml数据，然后根据生成数据类型的不同按照不同的解析规则解析xml并生成相应数据；
	 * 如果以request方式接收数据，首先获得request域的所有键值，根据前缀匹配待组装的字段，最后根据生成数据类型按照不同的解析规则生成相应的数据。
	 * 
	 * @param logicContext
	 *            逻辑上下文对象，记录结点运行时的上下文信息
	 * @throws Exception
	 */
	@Override
	public void doExecute(ILogicContext logicContext) throws Exception {
		ComponentManager.beforeExecuteComponent(this, this
				.createParameterContext(logicContext));

		try {
			if (SCOPE_XML.equals(this.getScope())) {
				int scopeInt = 2;

				if (logicContext instanceof IActionContext) {
					IActionContext actionContext = (IActionContext) logicContext;
					String xmlData = (String) actionContext.getValue(this
							.getXmlKey(), scopeInt);

					StringReader stringReader = new StringReader(xmlData);
					Document document = Dom4jUtils.getDocment(stringReader);
					Element root = document.getRootElement();
					logger.debug("      node : {execute : '{" + "key : '"
							+ getDataKey() + "', prefix : '" + prefix
							+ "', scope : '" + scope + "', class-type : '"
							+ classType + "', saturndata-space : '"
							+ saturnDataNamespace + "', saturndata-name : '"
							+ saturnDataType + "', xml-key  : '" + xmlKey
							+ "', xml-element-key : '" + elementKey
							+ "', xml-data : '" + xmlData + "'}', process : '"
							+ logicContext.getId() + "'}");

					if (DATA_KEY_LIST.equals(this.getDataType())) {
						List<SaturnData> saturnDataList = this
								.createSaturnDataList(root);

						actionContext.setValue(getDataKey(), saturnDataList);
						logger
								.debug("      node : {execute : '{ result : 'list', value : '"
										+ saturnDataList
										+ "'}', process : '"
										+ logicContext.getId() + "'}");
					} else if (DATA_DATAS_MAP.equals(this.classType)
							|| Map.class.getName().equals(this.classType)) {

						Map<String, Object> map = this.createMapValue(root);
						actionContext.setValue(getDataKey(), map);
						logger
								.debug("      node : {execute : '{ result : 'map', value : '"
										+ map
										+ "'}',process : '"
										+ logicContext.getId() + "'}");
					} else if (SaturnData.class.getName()
							.equals(this.classType)) {
						SaturnData saturnData = this
								.createSaturnDataValue(root);
						actionContext.setValue(getDataKey(), saturnData);
						logger
								.debug("      node : {execute : '{ result : 'saturn-data', value : '"
										+ saturnData
										+ "'}'"
										+ logicContext.getId() + "'}");
					}
				}
				// emily :新增接收类型json
			} else if (SCOPE_JSON.equals(this.getScope())) {
				int scopeInt = 2;

				if (logicContext instanceof IActionContext) {
					IActionContext actionContext = (IActionContext) logicContext;
					String value = actionContext.getValue(this.getXmlKey(),
							scopeInt).toString();
					logger.debug("      node : {execute : '{" + "key : '"
							+ getDataKey() + "', prefix : '" + prefix
							+ "', scope : '" + scope + "', class-type : '"
							+ classType + "', saturndata-space : '"
							+ saturnDataNamespace + "', saturndata-name : '"
							+ saturnDataType + "', json-key  : '" + this.getXmlKey()
							+ "'}', process : '" + logicContext.getId() + "'}");

					if (SaturnData.class.getName().equals(this.classType)) {
						SaturnData saturnData = createSaturnDataValue(value);
						actionContext.setValue(getDataKey(), saturnData);
						
						logger
						.debug("      node : {execute : '{ result : 'saturn-data', value : '"
								+ saturnData
								+ "'}'"
								+ logicContext.getId() + "'}");
					}
				}

			} else {
				int scopeInt = 1;
				logger.debug("      node : {execute : '{" + "key : '"
						+ getDataKey() + "', prefix : '" + prefix
						+ "', scope : '" + scope + "', class-type : '"
						+ classType + "', saturndata-space : '"
						+ saturnDataNamespace + "', saturndata-name : '"
						+ saturnDataType + "', xml-key  : '" + xmlKey
						+ "', xml-element-key : '" + elementKey
						+ "'}', process : '" + logicContext.getId() + "'}");

				scopeInt = Integer.parseInt(this.scope);
				Set<String> keys = logicContext.getValueKeys(scopeInt);
				Set<String> validKeys = this.getValidKeys(keys, prefix);

				if (DATA_DATAS_MAP.equals(this.classType)
						|| Map.class.getName().equals(this.classType)) {

					this.createMapValue(validKeys, logicContext);

				} else if (SaturnData.class.getName().equals(this.classType)) {
					this.createSaturnDataValue(validKeys, logicContext);
				}
			}
		} catch (Exception e) {
			logger.error("ERROR : { message : '"
					+ ExceptionUtils.getExMessage(e) + "', process : '"
					+ logicContext.getId() + "', node : '"
					+ super.getNodeType() + " " + super.getId() + " "
					+ super.getName() + "'}");
			throw e;

		} finally {
			ComponentManager.afterExecuteComponent(this, this
					.createParameterContext(logicContext));
		}
	}

	// emily :json拼装成SaturnData
	private SaturnData createSaturnDataValue(String jsondata)
			throws JSONException {

		SaturnData saturnData = SaturnDataManager.getInstance().createData(
				this.saturnDataNamespace, this.saturnDataType);
		IDataInfo saturnDataInfo = saturnData.getSaturnDataInfo();
		Set<String> keySet = saturnDataInfo.keySet();

		Map<String, Object> map = getJsonStringToMap(jsondata);

		for (String key : keySet) {
			if (map.containsKey(key)) {
				saturnData.set(key, map.get(key));
			}
		}
		return saturnData;
	}

	// emily: json转换成map
	private Map<String, Object> getJsonStringToMap(String jsonStr)
			throws JSONException {
		Map<String, Object> map = new HashMap<String, Object>();

		JSONObject json = new JSONObject(jsonStr);
		Map<Object, Object> jsonMap = json.getMap();
		
		Iterator<Object> iter = jsonMap.keySet().iterator();

		while (iter.hasNext()) {
			String key = iter.next().toString();

			if (this.hasPrefix) {
				if (key.startsWith(prefix)) {
					key = key.substring(prefix.length() + 1);
				}
			}

			Object value = jsonMap.get(key);
			if (value instanceof JSONObject) {
				map.put(key, ((JSONObject)value).getMap());
				map.putAll(getJsonStringToMap(value.toString()));
			} else {
				map.put(key, value);
			}
		}

		return map;
	}

	@SuppressWarnings("unchecked")
	private SaturnData createSaturnDataValue(Element root) {
		SaturnData saturnData = SaturnDataManager.getInstance().createData(
				this.saturnDataNamespace, this.saturnDataType);

		IDataInfo saturnDataInfo = saturnData.getSaturnDataInfo();
		Set<String> keySet = saturnDataInfo.keySet();
		List<Element> maps = root.elements(DATA_DATAS_MAP);
		List<Element> items = null;

		for (Element mapElement : maps) {

			if (mapElement.attributeValue(DATA_DATAS_KEY).equals(
					getElementKey())) {

				items = mapElement.elements(DATA_DATAS_VALUE);
			}
		}

		if (items != null) {

			for (Element item : items) {
				String attributeKey = item.attributeValue(DATA_DATAS_KEY);

				if (attributeKey != null) {

					if (this.hasPrefix) {

						if (attributeKey.startsWith(prefix)) {
							String valueKey = attributeKey.substring(prefix
									.length() + 1);

							if (keySet.contains(valueKey)) {
								Object value = item.getTextTrim();

								if (value != null && !"".equals(value)) {
									saturnData.set(valueKey, transform(value));
								}
							}
						}

					} else if (keySet.contains(attributeKey)) {
						Object value = item.getTextTrim();

						if (value != null && !"".equals(value)) {

							saturnData.set(attributeKey, transform(value));
						}
					}
				}
			}

		} else {
			logger
					.warn("create saturn data from xml; the element name in xml is ["
							+ this.getElementKey()
							+ "]! but it is not be found in xml!");
		}
		return saturnData;
	}

	@SuppressWarnings("unchecked")
	private Map<String, Object> createMapValue(Element root) {
		Map<String, Object> map = new HashMap<String, Object>();
		List<Element> maps = root.elements(DATA_DATAS_MAP);
		List<Element> items = null;

		for (Element mapElement : maps) {

			if (mapElement.attributeValue(DATA_DATAS_KEY).equals(
					getElementKey())) {
				items = mapElement.elements(DATA_DATAS_VALUE);
			}
		}

		for (Element item : items) {
			String attributeKey = item.attributeValue(DATA_DATAS_KEY);

			if (attributeKey != null) {

				if (this.hasPrefix) {

					if (attributeKey.startsWith(prefix + DATA_KEY_SEPARATOR)) {
						String valueKey = attributeKey.substring(this.prefix
								.length() + 1);

						Object value = item.getTextTrim();

						if ("".equals(value)) {
							value = null;
						}
						map.put(valueKey, transform(value));
					}

				} else {
					Object value = item.getTextTrim();

					if ("".equals(value)) {
						value = null;
					}
					map.put(attributeKey, transform(value));
				}
			}
		}
		return map;
	}

	@SuppressWarnings("unchecked")
	private List<SaturnData> createSaturnDataList(Element root) {
		List<SaturnData> saturnDataList = new ArrayList<SaturnData>();
		List<Element> elements = root.elements(DATA_DATAS_LIST);
		List<Element> saturnDatas = null;

		for (Element element : elements) {

			if (element.attributeValue(DATA_DATAS_KEY).equals(elementKey)) {
				saturnDatas = element.elements(DATA_DATAS_MAP);
			}
		}

		if (saturnDatas != null) {

			for (Element map : saturnDatas) {
				List<Element> items = map.elements(DATA_DATAS_VALUE);
				SaturnData saturnData = SaturnDataManager.getInstance()
						.createData(this.getSaturnDataNamespace(),
								this.getSaturnDataType());

				IDataInfo saturnDataInfo = saturnData.getSaturnDataInfo();
				Set<String> keySet = saturnDataInfo.keySet();

				for (Element value : items) {
					String attributeKey = value.attributeValue(DATA_DATAS_KEY);

					if (attributeKey != null) {

						if (this.hasPrefix) {

							if (attributeKey.startsWith(prefix
									+ DATA_KEY_SEPARATOR)) {

								String itemKey = attributeKey.substring(prefix
										.length() + 1);

								if (keySet.contains(itemKey)) {
									Object valueText = value.getTextTrim();

									if (valueText != null
											&& !"".equals(valueText)) {

										saturnData.set(itemKey,
												transform(valueText));
									}
								}
							}

						} else if (keySet.contains(attributeKey)) {
							Object valueText = value.getTextTrim();

							if (valueText != null && !"".equals(valueText)) {

								saturnData.set(attributeKey,
										transform(valueText));
							}
						}
					}
				}
				saturnDataList.add(saturnData);
			}
		}
		return saturnDataList;
	}

	private Set<String> getValidKeys(Set<String> keys, String prefix) {

		if (prefix == null || "".equals(prefix)) {
			return keys;
		}

		Set<String> validKeys = new HashSet<String>();

		for (String key : keys) {

			if (key.startsWith(prefix + DATA_KEY_SEPARATOR)) {
				validKeys.add(key);
			}
		}
		return validKeys;
	}

	private void createMapValue(Set<String> validKeys,
			ILogicContext logicContext) {

		Map<String, Object> map = new HashMap<String, Object>();

		for (String key : validKeys) {

			if (this.hasPrefix) {
				String valueKey = key.substring(this.prefix.length() + 1);
				Object value = logicContext.getValue(key);

				if ("".equals(value)) {
					value = null;
				}
				map.put(valueKey, value);

			} else {
				Object value = logicContext.getValue(key);

				if ("".equals(value)) {
					value = null;
				}
				map.put(key, value);
			}
		}
		logicContext.setValue(this.dataKey, map);
		logger.debug("execute saturn data Node " + super.getId()
				+ " create map, value is " + map.toString());
	}

	private void createSaturnDataValue(Set<String> validKeys,
			ILogicContext logicContext) {

		SaturnData saturnData = SaturnDataManager.getInstance().createData(
				this.saturnDataNamespace, this.saturnDataType);

		IDataInfo dataInfo = SaturnDataManager.getInstance().getSaturnDataInfo(
				this.saturnDataNamespace, this.saturnDataType);

		Set<String> keySet = dataInfo.keySet();

		if (dataInfo != null) {

			for (String key : validKeys) {

				if (this.hasPrefix) {
					String valueKey = key.substring(prefix.length() + 1);
					IDataItem dataItem = dataInfo.getDataItem(valueKey);

					if (dataItem != null) {
						Object value = logicContext.getValue(key);

						if (value != null && !"".equals(value)) {
							saturnData.set(valueKey, value);
						}
					}

				} else {

					if (keySet.contains(key)) {
						IDataItem dataItem = dataInfo.getDataItem(key);

						if (dataItem != null) {
							Object value = logicContext.getValue(key);

							if (value != null && !"".equals(value)) {
								saturnData.set(key, value);
							}
						}
					}
				}
			}
			logicContext.setValue(this.dataKey, saturnData);
			logger.debug("execute saturn data Node " + super.getId()
					+ " create saturndata, value is " + saturnData.toString());
		}
	}

	private Object transform(Object value) {

		if (value != null && !"".equals(value)) {
			String valueStr = (String) value;
			valueStr = valueStr.replace(LARGE_THAN, ">");
			valueStr = valueStr.replace(LESS_THAN, "<");
			return valueStr;
		}

		return value;
	}

	protected IParameterContext createParameterContext(
			ILogicContext logicContext) throws Exception {

		if (SaturnDebugThreadsManager.getInstance().isStart()) {
			initParameterInfos();
			return logicContext.createParameterContext(getParameterInfos());
		}
		return null;
	}

	private void initParameterInfos() {
		List<IParameterInfo> parameters = new ArrayList<IParameterInfo>();
		SaturnParameterInfo dataParameter = new SaturnParameterInfo();
		Class<?> dataType = null;

		if (DATA_KEY_LIST.equals(this.getDataType())) {
			dataType = List.class;

		} else if (DATA_DATAS_MAP.equals(this.classType)
				|| Map.class.getName().equals(this.classType)) {

			dataType = Map.class;

		} else if (SaturnData.class.getName().equals(this.classType)) {
			dataType = SaturnData.class;
		}
		dataParameter.setClassType(dataType);
		dataParameter.setId("1");
		dataParameter.setName("data");
		dataParameter.setPassingType(IParameterInfo.PASSING_IN_OUT);
		dataParameter.setScope(IParameterInfo.SCOPE_LOGIC);
		dataParameter.setValueKey(this.dataKey);
		parameters.add(dataParameter);

		SaturnParameterInfo prefixParameter = new SaturnParameterInfo();
		prefixParameter.setClassType(String.class);
		prefixParameter.setId("2");
		prefixParameter.setName("prefix");
		prefixParameter.setPassingType(IParameterInfo.PASSING_IN);
		prefixParameter.setScope(IParameterInfo.SCOPE_LOGIC);
		prefixParameter.setValueKey("'" + this.prefix + "'");
		parameters.add(prefixParameter);

		SaturnParameterInfo scopeParameter = new SaturnParameterInfo();
		scopeParameter.setClassType(String.class);
		scopeParameter.setId("3");
		scopeParameter.setName("scope");
		scopeParameter.setPassingType(IParameterInfo.PASSING_IN);
		scopeParameter.setScope(IParameterInfo.SCOPE_LOGIC);
		scopeParameter.setValueKey("'" + this.scope + "'");
		parameters.add(scopeParameter);

		SaturnParameterInfo fullKeyParameter = new SaturnParameterInfo();
		fullKeyParameter.setClassType(String.class);
		fullKeyParameter.setId("4");
		fullKeyParameter.setName("full key");
		fullKeyParameter.setPassingType(IParameterInfo.PASSING_IN);
		fullKeyParameter.setScope(IParameterInfo.SCOPE_LOGIC);
		fullKeyParameter.setValueKey("'" + this.saturnDataNamespace + "::"
				+ this.saturnDataType + "'");

		parameters.add(fullKeyParameter);

		SaturnParameterInfo xmlParameter = new SaturnParameterInfo();
		xmlParameter.setClassType(String.class);
		xmlParameter.setId("5");
		xmlParameter.setName("xml");
		xmlParameter.setPassingType(IParameterInfo.PASSING_IN);
		xmlParameter.setScope(IParameterInfo.SCOPE_LOGIC);
		xmlParameter.setValueKey(this.xmlKey);
		parameters.add(xmlParameter);

		SaturnParameterInfo xmlElementParameter = new SaturnParameterInfo();
		xmlElementParameter.setClassType(String.class);
		xmlElementParameter.setId("6");
		xmlElementParameter.setName("element");
		xmlElementParameter.setPassingType(IParameterInfo.PASSING_IN);
		xmlElementParameter.setScope(IParameterInfo.SCOPE_LOGIC);
		xmlElementParameter.setValueKey("'" + this.elementKey + "'");
		parameters.add(xmlElementParameter);
		super.setParameterInfos(parameters);
	}

	public ISaturnElement toSaturnElement() {
		ISaturnElement saturnDataElement = new SaturnElement(
				DataNodeInfoLoader.KEY_NODETYPE_DATA);

		saturnDataElement
				.addAttribute(NodeInfoLoader.KEY_NODE_ID, this.getId());
		saturnDataElement.addAttribute(NodeInfoLoader.KEY_NODE_NEXT, this
				.getNextId());

		saturnDataElement.addAttribute(NodeInfoLoader.KEY_NODE_X, this.getX());
		saturnDataElement.addAttribute(NodeInfoLoader.KEY_NODE_Y, this.getY());

		ISaturnElement nameElement = new SaturnElement(
				NodeInfoLoader.KEY_NODE_NAME, this.getName());

		ISaturnElement scopeElement = new SaturnElement(
				DataNodeInfoLoader.KEY_DATA_SCOPE, this.scope);

		ISaturnElement prefixElement = new SaturnElement(
				DataNodeInfoLoader.KEY_DATA_PREFIX, this.prefix);

		ISaturnElement dataKeyElement = new SaturnElement(
				DataNodeInfoLoader.KEY_DATA_KEY, this.dataKey);

		ISaturnElement elementKeyElement = new SaturnElement(
				DataNodeInfoLoader.KEY_DATA_ELEMENTKEY, this.elementKey);

		ISaturnElement xmlKeyElement = new SaturnElement(
				DataNodeInfoLoader.KEY_DATA_XMLKEY, this.xmlKey);

		ISaturnElement parametersElement = new SaturnElement(
				NodeInfoLoader.KEY_PARAMETER_LIST);

		ISaturnElement descriptionElement = new SaturnElement(
				NodeInfoLoader.KEY_NODE_DESCRIPTION, this.getDescription());

		ISaturnElement dataTypeElement = new SaturnElement(
				DataNodeInfoLoader.KEY_DATA_TYPE);

		dataTypeElement.addAttribute(
				DataNodeInfoLoader.KEY_DATA_TYPE_ATTRIBUTE_CLASS_TYPE,
				this.classType);

		dataTypeElement.addAttribute(
				DataNodeInfoLoader.KEY_DATA_TYPE_ATTRIBUTE_NAMESPACE,
				this.saturnDataNamespace);

		dataTypeElement.addAttribute(
				DataNodeInfoLoader.KEY_DATA_TYPE_ATTRIBUTE_TITTAN_DATA_TYPE,
				this.saturnDataType);

		saturnDataElement.addSubElement(nameElement);
		saturnDataElement.addSubElement(scopeElement);
		saturnDataElement.addSubElement(prefixElement);
		saturnDataElement.addSubElement(dataKeyElement);
		saturnDataElement.addSubElement(elementKeyElement);
		saturnDataElement.addSubElement(xmlKeyElement);
		saturnDataElement.addSubElement(parametersElement);
		saturnDataElement.addSubElement(descriptionElement);
		saturnDataElement.addSubElement(dataTypeElement);
		return saturnDataElement;
	}

	public static void main(String[] args) throws Exception {
		JSONObject json = new JSONObject("{kk:{a:1, b:2}}");
		System.out.println(json.get("kk"));
	}
}